package com.opensky.qatest.util.selenium;

import org.apache.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.testng.Reporter;

public class Report extends Reporter {

    private static final Logger LOGGER = Logger.getLogger(Report.class);

    private static final String OPEN_URL = "INFO: url \"%s\" is opening!";

    private static final String SEPARATOR = "***********************************************************************";

    private static final String TEST_INIT_START = "INFO: preaparation for test \"%s\" is started!";

    private static final String TEST_INIT_FINISH = "INFO: preaparation for test \"%s\" is finished!";

    private static final String TEST_STARTED = "INFO: test \"%s\" is started!";

    private static final String TEST_FINISHED_SUCCESS = "INFO: test \"%s\" is finished SUCCESSFULLY!";

    private static final String TEST_FINISHED_FAILURE = "INFO: test \"%s\" is finished with VALIDATION FAILURES!";

    private static final String WRONG_URL = "FAIL: wrong URL, expected \"%s\"> but actual \"%s\"!";

    private static final String NOT_LOADED = "FAIL: \"%s\" is not loaded!";

    private static final String NOT_LOADED_COMMENT = "FAIL: %s => \"%s\" is not loaded!";

    private static final String ELEMENT_PRESENT = "PASS: element \"%s\" presents!";

    private static final String ELEMENT_NOT_PRESENT = "FAIL: element \"%s\" does not present!";

    private static final String UNEXPECTED_ELEMENT_PRESENT = "FAIL: unexpected element \"%s\" presents!";

    private static final String ELEMENT_WITH_TEXT_PRESENT = "PASS: element \"%s\" with text \"%s\" presents!";

    private static final String ELEMENT_WITH_TEXT_NOT_PRESENT = "FAIL: element \"%s\" with text: \"%s\" does not present!";

    private static final String UNEXPECTED_ELEMENT_WITH_TEXT_PRESENT = "FAIL: unexpected element \"%s\" with text \"%s\" present!";

    private static final String ELEMENT_CLICK = "PASS: element \"%s\" is clicked!";

    private static final String ELEMENT_HOVER = "PASS: element \"%s\" is hovered!";

    private static final String ELEMENT_SEND_KEYS = "PASS: keys \"%s\" is sent to element \"%s\"!";

    private boolean isVerificationFailed;

    private WebDriver driver;

    public Report(WebDriver driver) {
	this.driver = driver;
	isVerificationFailed = false;
    }

    public static String wrongURL(String expected, String actual) {
	return String.format(WRONG_URL, expected, actual);
    }

    public static String notLoaded(String element) {
	return String.format(NOT_LOADED, element);
    }

    public static String notLoadedWithComment(String element, String comment) {
	return String.format(NOT_LOADED_COMMENT, comment, element);
    }

    public static void logTestStartInit(Class<?> clazz) {
	LOGGER.info(SEPARATOR);
	LOGGER.info(String.format(TEST_INIT_START, clazz.getSimpleName()));
    }

    public static void logTestFinishInit(Class<?> clazz) {
	LOGGER.info(String.format(TEST_INIT_FINISH, clazz.getSimpleName()));
	LOGGER.info(SEPARATOR);
    }

    public static void logTestStart(Class<?> clazz) {
	LOGGER.info(SEPARATOR);
	LOGGER.info(String.format(TEST_STARTED, clazz.getSimpleName()));
    }

    public static void logTestFinishSuccess(Class<?> clazz) {
	LOGGER.info(String.format(TEST_FINISHED_SUCCESS, clazz.getSimpleName()));
	LOGGER.info(SEPARATOR);
    }

    public static void logTestFinishFailure(Class<?> clazz) {
	LOGGER.info(String.format(TEST_FINISHED_FAILURE, clazz.getSimpleName()));
	LOGGER.info(SEPARATOR);
    }

    public String logOpenURL(String url) {
	LOGGER.info(String.format(OPEN_URL, url));
	return String.format(OPEN_URL, url);
    }

    public String logElementPresent(String name) {
	LOGGER.info(String.format(ELEMENT_PRESENT, name));
	return String.format(ELEMENT_PRESENT, name);
    }

    public String logElementNotPresent(String name) {
	LOGGER.info(String.format(ELEMENT_NOT_PRESENT, name));
	log(String.format(ELEMENT_NOT_PRESENT, name));
	if (!(driver instanceof HtmlUnitDriver)) {
	    log(Screenshot.take(name, driver));
	}
	isVerificationFailed = true;
	return String.format(ELEMENT_NOT_PRESENT, name);
    }

    public String logUnexpectedElementPresent(String name) {
	LOGGER.info(String.format(UNEXPECTED_ELEMENT_PRESENT, name));
	log(String.format(UNEXPECTED_ELEMENT_PRESENT, name));
	if (!(driver instanceof HtmlUnitDriver)) {
	    log(Screenshot.take(name, driver));
	}
	isVerificationFailed = true;
	return String.format(UNEXPECTED_ELEMENT_PRESENT, name);
    }

    public String logElementWithTextPresent(String name, String text) {
	LOGGER.info(String.format(ELEMENT_WITH_TEXT_PRESENT, name, text));
	return String.format(ELEMENT_WITH_TEXT_PRESENT, name, text);
    }

    public String logElementWithTextNotPresent(String name, String text) {
	LOGGER.info(String.format(ELEMENT_WITH_TEXT_NOT_PRESENT, name, text));
	log(String.format(ELEMENT_WITH_TEXT_NOT_PRESENT, name, text));
	if (!(driver instanceof HtmlUnitDriver)) {
	    log(Screenshot.take(name, driver));
	}
	isVerificationFailed = true;
	return String.format(ELEMENT_WITH_TEXT_NOT_PRESENT, name, text);
    }

    public String logUnexpectedElementWithTextPresent(String name, String text) {
	LOGGER.info(String.format(UNEXPECTED_ELEMENT_WITH_TEXT_PRESENT, name, text));
	log(String.format(UNEXPECTED_ELEMENT_WITH_TEXT_PRESENT, name, text));
	if (!(driver instanceof HtmlUnitDriver)) {
	    log(Screenshot.take(name, driver));
	}
	isVerificationFailed = true;
	return String.format(UNEXPECTED_ELEMENT_WITH_TEXT_PRESENT, name, text);
    }

    public String elementIsClicked(String name) {
	LOGGER.info(String.format(ELEMENT_CLICK, name));
	return String.format(ELEMENT_CLICK, name);
    }

    public String elementIsHovered(String name) {
	LOGGER.info(String.format(ELEMENT_HOVER, name));
	return String.format(ELEMENT_HOVER, name);
    }

    public String elementSendKeys(String name, String keys) {
	LOGGER.info(String.format(ELEMENT_SEND_KEYS, keys, name));
	return String.format(ELEMENT_SEND_KEYS, keys, name);
    }

    public boolean isVerificationFailed() {
	return isVerificationFailed;
    }
}
